using System;
using System.Collections.Generic;
using System.Collections;
using System.Threading.Tasks;

namespace QQZiFramework.MQ
{
    public class RedisMQ : IMQDriver
    {
        DBContext Context;
        public static int RedisMQ_DBINDEX = 0;

        public void Publish(string queueName, object obj)
        {
            if (Context == null) Context = new DBContext() { LogSql = SqlLogMode.NoLog };
            Context.GetRedisDatabase(RedisMQ_DBINDEX).SetListItem(queueName, obj);
        }

        public long GetLength(string queueName)
        {
            if (Context == null) Context = new DBContext() { LogSql = SqlLogMode.NoLog };
            return Context.GetRedisDatabase(RedisMQ_DBINDEX).GetListLength(queueName);
        }

        Hashtable ht = new Hashtable();

        public void BindReceived(string queueName, Func<byte[], bool> fun)
        {
            if (Context == null) Context = new DBContext() { LogSql = SqlLogMode.NoLog };
            ht.Add(queueName, fun);
            System.Threading.Thread newThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(monitor));
            newThread.Start(queueName);
        }

        public void BindReceivedAsync(string queueName, Func<byte[], Task<bool>> fun)
        {
            if (Context == null) Context = new DBContext() { LogSql = SqlLogMode.NoLog };
            ht.Add(queueName, fun);
            System.Threading.Thread newThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(monitor));
            newThread.Start(queueName);
        }

        private async void monitor(object obj)
        {
            string queueName = (string)obj;
            while (true)
            {
                string str = Context.GetRedisDatabase(RedisMQ_DBINDEX).PopListItem<string>(queueName);
                if (str != null)
                {
                    try
                    {
                        bool asyncTask = ht[obj] is Func<byte[], Task<bool>>;
                        if (asyncTask)
                        {
                            var fun = ht[obj] as Func<byte[], Task<bool>>;
                            await fun(System.Text.Encoding.UTF8.GetBytes(str));
                        }
                        else
                        {
                            var fun = ht[obj] as Func<byte[], bool>;
                            fun.Invoke(System.Text.Encoding.UTF8.GetBytes(str));
                        }
                    }
                    catch (Exception ex)
                    {
                        //重新加进队列
                        Context.LogException(ex, "RedisMQ");
                        //Context.GetRedisDatabase(RedisMQ_DBINDEX).SetListItem(queueName, str);
                    }
                }
                else
                {
                    System.Threading.Thread.Sleep(3000);
                }

            }
        }
    }
}
